<template>
  <ConfigProvider :locale="getAntdLocale">
    <Modal v-bind="getProps">
      <Spin :spinning="loading">
        <div style="padding: 20px">
          <div v-html="options.content" style="margin-bottom: 8px"></div>
          <BasicForm @register="registerForm">
            <template #customInput="{ model, field }">
              <Input ref="inputRef" v-model:value="model[field]" :placeholder="placeholder" @pressEnter="onSubmit" @input="onChange" />
            </template>
          </BasicForm>
        </div>
      </Spin>
    </Modal>
  </ConfigProvider>
</template>

<script lang="ts">
import type { PromptFormProps } from './typing';
import type { ModalProps } from '@/components/Modal';
import { ref, defineComponent, computed, unref, onMounted, nextTick } from 'vue';
import { BasicForm, useForm } from '@/components/Form';
import { Modal, Spin, Input, ConfigProvider } from 'ant-design-vue';
import { useLocale } from '@/locales/useLocale';

export default defineComponent({
  name: 'PromptForm',
  components: {
    Modal,
    Spin,
    Input,
    BasicForm,
    ConfigProvider,
  },
  emits: ['register'],
  setup(props, { emit }) {
    const inputRef = ref();
    const { getAntdLocale } = useLocale();
    const visible = ref(false);
    // 当前是否正在加载中
    const loading = ref(false);
    const options = ref<PromptFormProps>({});
    const placeholder = computed(() => options.value.placeholder ?? '请输入内容');
    // 注册表单
    const [registerForm, { clearValidate, setFieldsValue, validate, updateSchema }] = useForm({
      compact: true,
      wrapperCol: { span: 24 },
      schemas: [
        {
          label: '',
          field: 'input',
          component: 'Input',
          slot: 'customInput',
        },
      ],
      showActionButtonGroup: false,
    });

    // 弹窗最终props
    const getProps = computed(() => {
      let opt = options.value;
      let modalProps: Partial<ModalProps> = {
        width: (opt.width ?? 500) as number,
        title: (opt.title ?? 'prompt') as string,
        visible: unref(visible),
        confirmLoading: unref(loading),
      };
      let finalProps: Recordable = {
        ...modalProps,
        ...props,
        ...opt,
        onOk: onSubmit,
        onCancel() {
          if (typeof options.value.onCancel === 'function') {
            options.value.onCancel();
          }
          close();
        },
      };
      return finalProps;
    });

    onMounted(() => {
      emit('register', {
        openModal,
        setLoading,
        getVisible: visible,
      });
    });

    /** 弹窗开启 */
    async function openModal(opt: any) {
      document.body.focus();

      options.value = opt;
      visible.value = true;
      await nextTick();
      await updateSchema({
        field: 'input',
        required: options.value.required,
        rules: options.value.rules,
        dynamicRules: options.value.dynamicRules,
      } as any);
      await setFieldsValue({
        input: options.value.defaultValue ?? '',
      });
      await clearValidate();
      inputRef.value?.focus();
    }

    /** 弹窗关闭 */
    function close() {
      visible.value = false;
    }

    function onChange() {
      validate();
    }

    /** 提交表单 */
    async function onSubmit() {
      try {
        const { onOk } = options.value;
        // 表单验证
        let values = await validate();
        setLoading(true);
        if (typeof onOk === 'function') {
          let flag = await onOk(values.input);
          // 只有返回 false 才阻止关闭弹窗
          if (!(flag === false)) {
            close();
          }
        } else {
          close();
        }
      } finally {
        setLoading(false);
      }
    }

    /** 设置加载状态*/
    function setLoading(flag) {
      loading.value = flag;
    }

    return {
      inputRef,
      getProps,
      loading,
      options,
      placeholder,
      getAntdLocale,
      onChange,
      onSubmit,

      registerForm,
    };
  },
});
</script>
